from django.contrib.auth import get_user_model
from django.conf import settings
from django.contrib.auth import login as dj_login
from django.contrib.auth.views import LogoutView as DjLogoutView
from django.shortcuts import resolve_url
from django.utils.http import is_safe_url
from django.utils.decorators import method_decorator
from django.views.generic import FormView
from django.views.decorators.debug import sensitive_post_parameters
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.cache import never_cache
from django.http import HttpResponseRedirect, JsonResponse
from django.contrib.auth.views import PasswordChangeView as DjPasswordChangeView, update_session_auth_hash

from .forms import LoginCaptchaForm, UserPasswordChangeForm

__all__ = ["login", "logout", "change_password"]

UserModel = get_user_model()


@method_decorator(sensitive_post_parameters('password', 'password1'), name='dispatch')
@method_decorator(csrf_protect, name='dispatch')
@method_decorator(never_cache, name='dispatch')
class LoginView(FormView):
    form_class = LoginCaptchaForm
    template_name = "users/login.html"
    redirect_field_name = "next"

    # def get(self, request, *args, **kwargs):
    #     if request.user.is_staff:
    #         return

    def dispatch(self, request, *args, **kwargs):
        if request.user.is_authenticated:
            response = HttpResponseRedirect(self.get_success_url())
            return response
        return super(LoginView, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = {
            "next": self.request.GET.get(self.redirect_field_name, ''),
            "action_path": self.request.get_full_path()
        }
        context.update(kwargs)
        return super(LoginView, self).get_context_data(**context)

    def get_success_url(self):
        url = self.get_redirect_url()
        return url or resolve_url(settings.LOGIN_REDIRECT_URL)

    def get_redirect_url(self):
        """Return the user-originating redirect URL if it's safe."""
        redirect_to = self.request.POST.get(
            self.redirect_field_name,
            self.request.GET.get(self.redirect_field_name, '')
        )
        url_is_safe = is_safe_url(
            url=redirect_to,
            allowed_hosts=set(),
            require_https=self.request.is_secure()
        )
        return redirect_to if url_is_safe else ''

    def form_valid(self, form):
        dj_login(self.request, form.user)
        remember = form.cleaned_data['remember']
        if remember:
            self.request.session.set_expiry(settings.SESSION_COOKIE_AGE)
        else:
            self.request.session.set_expiry(settings.SESSION_COOKIE_AGE / 2)
        return super(LoginView, self).form_valid(form)

    def get_form_kwargs(self):
        kwargs = super(LoginView, self).get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs


login = LoginView.as_view()


class LogoutView(DjLogoutView):
    redirect_field_name = 'next'
    template_name = 'users/logged_out.html'

    def get(self, request, *args, **kwargs):
        return super(LogoutView, self).get(request, *args, **kwargs)


logout = LogoutView.as_view()


class PasswordChangeView(DjPasswordChangeView):
    form_class = UserPasswordChangeForm

    def form_invalid(self, form):
        return JsonResponse({"success": False, "errors": form.errors})

    def form_valid(self, form):
        form.save()
        update_session_auth_hash(self.request, form.user)
        return JsonResponse(data={"success": True, "message": "修改成功"})


change_password = PasswordChangeView.as_view()
